#ifndef _SQLIST_
#define _SQLIST_

#include<stdio.h>
#include<stdlib.h>
#include<string.h>

#define SqList(T) T##_SqList
#define List(T) T##_List



#define SET_SQLIST_TYPE(T)           \
typedef struct List(T){              \
	T elem;                          \
	struct List(T) *ne;              \
} List(T);                           \
typedef struct SqList(T){            \
	void (*ClearList)();	         \
	void (*DestroyList)();           \
	int (*ListEmpty)();              \
	int (*ListLength)();             \
	T (*GetElem)(int i);             \
	int (*LocateElem)(T e);          \
	int (*ListInsert)(int i, T e);   \
	int (*ListDelet)(int i);         \
	List(T)* (*begin)();             \
	List(T)* (*end)();               \
	int (*push)(T e);                \
	void (*state)();                 \
}SqList(T)                                    \


#define FUNCTION_BADY(T)             \
void ClearList(){                    \
	length = 0;                      \
}                                    \
void DestroyList(){                  \
	length = 0;                      \
	free(head);                      \
	head = NULL;                     \
}                                    \
int ListEmpty(){                     \
	return length == 0;              \
}                                    \
int ListLength(){                    \
	return length;                   \
}                                    \
T GetElem(int i){                    \
	if(!(1 <= i && i <= length))     \
		return 0x3f3f3f3f;           \
	int st = 1;                      \
	List(T) *it = head;              \
	while(st < i){                   \
		it = it->ne;                 \
		st ++;                       \
	}                                \
	return it->elem;                 \
}                                    \
int LocateElem(T e){                 \
	List(T) *it = head;              \
	int pos = 0, i = 1;              \
	while(it != NULL){              \
		if(it -> elem == e){         \
			pos = i;                 \
			break;					 \
		}							 \
		it = it -> ne;				 \
		i ++;						 \
	}								 \
	return pos;                      \
}                                    \
List(T)* begin(){                    \
	return head;                     \
}                                    \
List(T)* end(){                      \
	return NULL;                     \
}                                    \
int push(T e){                       \
	List(T) *temp = (List(T)* )malloc(sizeof(List(T))*1);\
	if(temp == NULL) return 0;       \
	temp -> elem = e;                \
	temp -> ne = head;               \
	head = temp;                     \
	length ++;                       \
	return 1;                        \
}                                    \
int ListInsert(int i, T e){          \
	if(i<=0 || length + 1 < i)      \
		return 0;                    \
	int pos = 1;                     \
	List(T)* it = begin();           \
    List(T)* temp = (List(T)* )malloc(sizeof(List(T))*1);\
    temp -> elem = e;                \
    while(pos < i - 1){              \
        it = it -> ne;               \
        pos++;                       \
    }                                \
    if(it == NULL){                  \
        head = temp;                   \
        head -> ne = NULL;             \
    }else{                           \
        temp -> ne = it -> ne;       \
        it -> ne = temp;             \
    }                                \
                                     \
	length++;	                     \
	return 1;                        \
}                           		 \
int ListDelet(int i){                \
	if(i<=0 || length < i)           \
		return 0;                    \
	int pos = 1;                     \
	List(T)* it = begin();           \
	List(T)* temp;                   \
	if(i == 1){                      \
        temp = it;                   \
        head = head->ne;             \
	}                                \
	else{                            \
        while(pos < i - 1){          \
            it = it -> ne;           \
            pos ++;                  \
        }                            \
        temp = it->ne;               \
        it->ne = temp->ne;           \
	}                                \
	free(temp);                      \
	length--;                        \
	return 1;                        \
}                                    \
void state(){           \
    printf("链表长度：%d\n", a.ListLength());\
    puts("链表元素：");\
    for(List(int) *it = begin();it != end(); it = it->ne){\
        printf("%d ", it->elem);\
    }\
    putchar('\n');\
    printf("是否为空：%s\n", (a.ListEmpty() != 0 ? "true" : "false"));\
}\


#define FUNCTION_ASS                 \
this.ClearList = ClearList;          \
this.DestroyList = DestroyList;      \
this.ListEmpty = ListEmpty;          \
this.ListLength = ListLength;        \
this.GetElem = GetElem;              \
this.LocateElem = LocateElem;        \
this.begin = begin;                  \
this.end = end;                      \
this.push = push;                    \
this.ListInsert = ListInsert;        \
this.ListDelet = ListDelet;          \
this.state = state;

#define InitList(T)                  \
({                                   \
	List(T) *head = NULL;            \
	int length = 0;                  \
	SqList(T) this;                  \
	FUNCTION_BADY(T)                 \
	FUNCTION_ASS                     \
	this;                            \
})


#endif
